package pers.lolicer.redtidelibrary.utils

import android.Manifest
import android.annotation.SuppressLint
import android.app.Activity
import android.content.Context
import android.content.Intent
import android.graphics.Bitmap
import android.graphics.pdf.PdfRenderer
import android.net.Uri
import android.provider.DocumentsContract
import android.provider.OpenableColumns
import android.util.Log
import androidx.activity.ComponentActivity
import androidx.activity.compose.ManagedActivityResultLauncher
import androidx.activity.compose.rememberLauncherForActivityResult
import androidx.activity.result.ActivityResult
import androidx.activity.result.contract.ActivityResultContracts
import androidx.appcompat.content.res.AppCompatResources
import androidx.compose.runtime.Composable
import androidx.compose.runtime.MutableState
import androidx.compose.ui.graphics.ImageBitmap
import androidx.compose.ui.graphics.asImageBitmap
import androidx.core.app.ActivityCompat
import androidx.core.content.ContextCompat.startActivity
import androidx.core.net.toUri
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.launch
import pers.lolicer.redtidelibrary.R
import pers.lolicer.redtidelibrary.config.BitmapImageConfig
import pers.lolicer.redtidelibrary.repository.MyDatabase
import pers.lolicer.redtidelibrary.repository.entity.BookEntity
import java.io.File
import java.io.FileOutputStream
import java.io.InputStream
import java.util.stream.IntStream.range

class FileUtils {
    // 启动文件选择器并处理选择结果
    @Composable
    fun fileSelectorLauncher(context: Context, isDataSync: MutableState<Boolean>): ManagedActivityResultLauncher<Intent, ActivityResult> {
        return rememberLauncherForActivityResult(ActivityResultContracts.StartActivityForResult()) { result ->
            if (result.resultCode == ComponentActivity.RESULT_OK) {
                result.data?.let { uri ->
                    // 单选
                    if(uri.data != null){
                        Log.d("fileUri", uri.data.toString())

                        val fileUri = uri.data!! // 类似 content://com.android.providers.downloads.documents/document/msf%3A1000131004
                        // Log.d("docId", DocumentsContract.getDocumentId(fileUri)) // 类似msf:1000131004

                        context.contentResolver.takePersistableUriPermission(fileUri, Intent.FLAG_GRANT_READ_URI_PERMISSION)
                        context.contentResolver.takePersistableUriPermission(fileUri, Intent.FLAG_GRANT_WRITE_URI_PERMISSION)

                        saveBookToRoom(context, fileUri)
                    }
                    // 多选
                    else if(uri.clipData != null){
                        Log.d("Number of selected files", uri.clipData?.itemCount.toString())
                        for(idx in uri.clipData?.itemCount?.let { range(0, it) }!!){
                            val fileUri = uri.clipData?.getItemAt(idx)?.uri
                            Log.d("fileUri$idx", fileUri.toString())
                            // Log.d("docId", DocumentsContract.getDocumentId(fileUri))

                            if(fileUri != null){
                                context.contentResolver.takePersistableUriPermission(fileUri, Intent.FLAG_GRANT_READ_URI_PERMISSION)
                                context.contentResolver.takePersistableUriPermission(fileUri, Intent.FLAG_GRANT_WRITE_URI_PERMISSION)

                                saveBookToRoom(context, fileUri)
                            }
                            else{
                                throw Exception("Error: 文件uri为空！")
                            }
                        }
                    }
                    else{ // uri.data 和 uri.clipData 均为null
                        throw Exception("Error: 添加时出现错误！")
                    }
                }

                isDataSync.value = false
            }
        }
    }

    fun saveBookToRoom(context: Context, contentUri: Uri){
        val bookDao = MyDatabase.getDB(context).getBookDao()
        val name = getDisplayNameFromUri(context, contentUri)
        if(name != ""){
            val be = BookEntity(
                uriString = contentUri.toString(),
                book_name = name,
                folder = "default",
                time_last_open = System.currentTimeMillis(),
                time_import = System.currentTimeMillis()
            )

            CoroutineScope(Dispatchers.IO).launch{
                val uris = bookDao.getAllUris()
                var hasEqual = false
                uris.forEach{uri ->
                    if(be.uriString.getID() == uri.getID()){
                        hasEqual = true
                        Log.i("saveBookToRoom:", "文件已存在，取消插入")
                    }
                }
                if(!hasEqual) bookDao.insertBook(be)
            }
        }
        else{
            Log.e("Save Book To Room Failed", "文件状态异常，保存文件失败")
        }
    }

    /**
     *  通过uri将文件保存在程序缓存中，并持久化读写权限。
     *
     *  用法：
     *  ```
     *  val file = saveFileToCache(context, fileUri)
     *  if(file != null){
     *      val absolutePath = file.absolutePath
     *      Log.d("SaveSuccess", absolutePath)
     *      // openFile(context, uri.data!!) // 测试用
     *  }
     *  else{
     *      Log.d("SaveFail", "Greeting: ")
     *  }
     *  ```
     * */
    fun saveFileToCache(context: Context, contentUri: Uri): File? {
        var inputStream: InputStream? = null
        var outputStream: FileOutputStream? = null
        var file: File? = null

        context.contentResolver.takePersistableUriPermission(contentUri, Intent.FLAG_GRANT_READ_URI_PERMISSION)
        context.contentResolver.takePersistableUriPermission(contentUri, Intent.FLAG_GRANT_WRITE_URI_PERMISSION)

        try {
            inputStream = context.contentResolver.openInputStream(contentUri)
            if (inputStream != null) {
                val cacheDir = context.cacheDir
                val displayName = getDisplayNameFromUri(context, contentUri)
                if(displayName == "") return file

                file = File(cacheDir, displayName)
                outputStream = FileOutputStream(file)
                val buffer = ByteArray(1024)
                var length: Int
                while (inputStream.read(buffer).also { length = it } > 0) {
                    outputStream.write(buffer, 0, length)
                }
            }
        } catch (e: Exception) {
            e.printStackTrace()
        } finally {
            inputStream?.close()
            outputStream?.close()
        }
        return file
    }

    // 通过uri获取文件名
    fun getDisplayNameFromUri(context: Context, contentUri: Uri): String {
//         context.grantUriPermission(context.packageName, contentUri, Intent.FLAG_GRANT_PERSISTABLE_URI_PERMISSION or Intent.FLAG_GRANT_READ_URI_PERMISSION)
//         context.contentResolver.takePersistableUriPermission(contentUri, Intent.FLAG_GRANT_READ_URI_PERMISSION or  Intent.FLAG_GRANT_WRITE_URI_PERMISSION)
        ActivityCompat.requestPermissions(context as Activity, arrayOf(Manifest.permission.READ_EXTERNAL_STORAGE), 1)

        try {
            val returnCursor = context.contentResolver.query(contentUri, null, null, null, null)
            returnCursor?.use { cursor ->
                if (cursor.moveToFirst()) {
                    val nameIndex = cursor.getColumnIndex(OpenableColumns.DISPLAY_NAME)
                    return cursor.getString(nameIndex) ?: ""
                }
            }
        }
        catch (e: SecurityException){
            e.printStackTrace()
            if(!checkFileExistence(context, contentUri))
                Log.e("文件状态异常", "Error: 文件"+ contentUri.toString() +"不存在！")
            return ""
        }
        return ""
    }

    // 通过uri获取文件大小
    fun getSizeFromUri(context: Context, contentUri: Uri): String {
        try {
            val returnCursor = context.contentResolver.query(contentUri, null, null, null, null)
            returnCursor?.use { cursor ->
                if (cursor.moveToFirst()) {
                    val nameIndex = cursor.getColumnIndex(OpenableColumns.SIZE)
                    return cursor.getString(nameIndex) ?: ""
                }
            }
        }
        catch (e: Exception){
            return ""
        }
        return ""
    }

    // 通过uri打开文件
    @SuppressLint("QueryPermissionsNeeded")
    fun openFile(context: Context, contentUri: Uri): Boolean{
        val intent = Intent(Intent.ACTION_VIEW).apply {
            data = contentUri
            addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION)
            // addCategory(Intent.CATEGORY_OPENABLE)
        }

        CoroutineScope(Dispatchers.IO).launch {
            val bookDao = MyDatabase.getDB(context).getBookDao()
            bookDao.updateTimeLastOpenByUri(System.currentTimeMillis(), contentUri.toString())
        }

        // if(intent.resolveActivity(context.packageManager) != null)
        try {
            startActivity(context, intent, null)
        }
        catch(e: Exception){
            return false
        }
        return true
    }

    fun checkFileExistence(context: Context, contentUri: Uri): Boolean{
        return try {
            context.contentResolver.openInputStream(contentUri)?.use {
                true
            } ?: false
        } catch (e: Exception) {
            false
        }
    }

    fun getCoverFromUri(context: Context, contentUri: Uri): ImageBitmap{
        val type = context.contentResolver.getType(contentUri)
        return when{
            type == null -> BitmapImageConfig.createBitmap(context, R.drawable.type_err)
            type == "application/pdf" -> PdfUtils().getPdfCoverFromUri(context, contentUri)
            type == "application/epub+zip" -> EpubUtils().getCover(context, contentUri)
            type.startsWith("image/") -> BitmapImageConfig.createBitmap(context, R.drawable.type_img)
            type == "text/plain" -> BitmapImageConfig.createBitmap(context, R.drawable.type_txt)
            type == "application/msword" -> BitmapImageConfig.createBitmap(context, R.drawable.type_docx)
            else -> BitmapImageConfig.createBitmap(context, R.drawable.type_oth)
        }
    }
}